package net.mimai.vultrue.bus.mybatisplus.interceptor;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import net.mimai.vultrue.bus.mybatisplus.expression.NullTenantValue;
import net.sf.jsqlparser.expression.*;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.expression.operators.relational.*;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.select.Select;

import java.util.List;

/**
 * @ClassName TenantBizInnerInterceptor
 * @Description 扩展mybatis自带的TenantLineInnerInterceptor，适应没有租户信息时，不执行租户策略
 * @Author 方丈
 * @Date 2021/10/27 14:06
 * @Version 1.0.0
 **/
public class TenantBizInnerInterceptor extends TenantLineInnerInterceptor {

    private TenantLineHandler tenantLineHandler;

    public TenantBizInnerInterceptor(final TenantLineHandler tenantLineHandler) {
        super(tenantLineHandler);
        this.tenantLineHandler = tenantLineHandler;
    }


    @Override
    protected void processInsert(Insert insert, int index, String sql, Object obj) {
        if (tenantLineHandler.ignoreTable(insert.getTable().getName())) {
            // 过滤退出执行
            return;
        }
        List<Column> columns = insert.getColumns();
        if (CollectionUtils.isEmpty(columns)) {
            // 针对不给列名的insert 不处理
            return;
        }
        String tenantIdColumn = tenantLineHandler.getTenantIdColumn();
        if (tenantLineHandler.ignoreInsert(columns, tenantIdColumn)) {
            // 针对已给出租户列的insert 不处理
            return;
        }
        columns.add(new Column(tenantIdColumn));

        Expression tenantIdExpress = tenantLineHandler.getTenantId();
        // fixed gitee pulls/141 duplicate update
        List<Expression> duplicateUpdateColumns = insert.getDuplicateUpdateExpressionList();
        if (CollectionUtils.isNotEmpty(duplicateUpdateColumns)) {
            if(tenantIdExpress ==null || tenantIdExpress instanceof NullTenantValue){

            }else{
                EqualsTo equalsTo = new EqualsTo();
                equalsTo.setLeftExpression(new StringValue(tenantIdColumn));
                equalsTo.setRightExpression(tenantIdExpress);
                duplicateUpdateColumns.add(equalsTo);
            }
        }

        Select select = insert.getSelect();
        if (select != null) {
            this.processInsertSelect(select.getSelectBody());
        } else if (insert.getItemsList() != null) {
            // fixed github pull/295
            ItemsList itemsList = insert.getItemsList();
            if(tenantIdExpress ==null || tenantIdExpress instanceof NullTenantValue){
            }else{
                if (itemsList instanceof MultiExpressionList) {
                    ((MultiExpressionList) itemsList).getExpressionLists().forEach(el -> el.getExpressions().add(tenantIdExpress));
                } else {
                    ((ExpressionList) itemsList).getExpressions().add(tenantIdExpress);
                }
            }
        } else {
            throw ExceptionUtils.mpe("Failed to process multiple-table update, please exclude the tableName or statementId");
        }
    }

    /**
     * delete update 语句 where 处理
     */
    @Override
    protected BinaryExpression andExpression(Table table, Expression where) {
        Expression tenantIdExpression = tenantLineHandler.getTenantId();
        if(tenantIdExpression ==null || tenantIdExpression instanceof NullTenantValue){
            //无租户信息，只能强行编码添加恒真的条件满足代码结构需要
            NotEqualsTo notEqualsTo = new NotEqualsTo();
            notEqualsTo.setLeftExpression(this.getAliasColumn(table));
            notEqualsTo.setRightExpression(new LongValue(0));
            if (null != where) {
                if (where instanceof OrExpression) {
                    return new AndExpression(notEqualsTo, new Parenthesis(where));
                } else {
                    return new AndExpression(notEqualsTo, where);
                }
            }
            return notEqualsTo;
        }

        //获得where条件表达式
        EqualsTo equalsTo = new EqualsTo();
        equalsTo.setLeftExpression(this.getAliasColumn(table));
        equalsTo.setRightExpression(tenantIdExpression);
        if (null != where) {
            if (where instanceof OrExpression) {
                return new AndExpression(equalsTo, new Parenthesis(where));
            } else {
                return new AndExpression(equalsTo, where);
            }
        }
        return equalsTo;
    }

    @Override
    protected Expression builderExpression(Expression currentExpression, Table table) {
        Expression tenantIdExpress = tenantLineHandler.getTenantId();
        if(tenantIdExpress ==null || tenantIdExpress instanceof NullTenantValue){
            return currentExpression;
        }

        EqualsTo equalsTo = new EqualsTo();
        equalsTo.setLeftExpression(this.getAliasColumn(table));
        equalsTo.setRightExpression(tenantIdExpress);
        if (currentExpression == null) {
            return equalsTo;
        }
        if (currentExpression instanceof OrExpression) {
            return new AndExpression(new Parenthesis(currentExpression), equalsTo);
        } else {
            return new AndExpression(currentExpression, equalsTo);
        }
    }
}
